<!DOCTYPE html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/jexo/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/jexo/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/jexo/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/jexo/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/jexo/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/jexo/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/jexo/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Android,封装," />










<meta name="description" content="本来在项目中是使用了Volley 然后封装 封装了一个HttpUtils,但是由于项目中要引入RxJava,所以就顺便替换一下Volley,使用Retrofit+RxJava。">
<meta name="keywords" content="Android,封装">
<meta property="og:type" content="article">
<meta property="og:title" content="Retrofit+RxJava完美封装">
<meta property="og:url" content="http://ja_project.gitee.io/jexo/2018/04/18/Retrofit+RxJava完美封装/index.html">
<meta property="og:site_name" content="Ling Hu Blog">
<meta property="og:description" content="本来在项目中是使用了Volley 然后封装 封装了一个HttpUtils,但是由于项目中要引入RxJava,所以就顺便替换一下Volley,使用Retrofit+RxJava。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-04-18T13:20:34.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Retrofit+RxJava完美封装">
<meta name="twitter:description" content="本来在项目中是使用了Volley 然后封装 封装了一个HttpUtils,但是由于项目中要引入RxJava,所以就顺便替换一下Volley,使用Retrofit+RxJava。">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/jexo/',
    scheme: 'Mist',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://ja_project.gitee.io/jexo/2018/04/18/Retrofit+RxJava完美封装/"/>





  <title>Retrofit+RxJava完美封装 | Ling Hu Blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?abc8796c232e2b898d516245257842b4";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/jexo/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Ling Hu Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/jexo/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/jexo/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/jexo/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/jexo/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/jexo/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://ja_project.gitee.io/jexo/jexo/2018/04/18/Retrofit+RxJava完美封装/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Ling Hu">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/jexo/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Ling Hu Blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Retrofit+RxJava完美封装</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-04-18T20:55:42+08:00">
                2018-04-18
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/jexo/categories/完美封装/" itemprop="url" rel="index">
                    <span itemprop="name">完美封装</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/jexo/2018/04/18/Retrofit+RxJava完美封装/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count gitment-comments-count" data-xid="/jexo/2018/04/18/Retrofit+RxJava完美封装/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>本来在项目中是使用了Volley 然后封装 封装了一个HttpUtils,<br>但是由于项目中要引入RxJava,所以就顺便替换一下Volley,使用Retrofit+RxJava。</p>
<a id="more"></a>
<p>Volley框架，我这里就 不过多介绍了，大家如果想学习的会可以自己去了解下。<br><a href="http://blog.csdn.net/ysh06201418/article/details/46443235" target="_blank" rel="noopener">http://blog.csdn.net/ysh06201418/article/details/46443235</a></p>
<p>首先大家可以参考下其他的Retrofit+RxJava的使用方法。<br><a href="http://blog.csdn.net/byxyrq/article/details/52672202" target="_blank" rel="noopener">http://blog.csdn.net/byxyrq/article/details/52672202</a></p>
<p>如果大家对RxJava还不大了解的话，大家可以看下这篇文章。<br><a href="http://gank.io/post/560e15be2dca930e00da1083" target="_blank" rel="noopener">http://gank.io/post/560e15be2dca930e00da1083</a></p>
<p>下面我介绍下我是如何封装Retrofit+RxJava的。<br>这是我公司的后台返回的json数据格式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;  </span><br><span class="line">    data:返回的数据,  </span><br><span class="line">    errorCode:200,  </span><br><span class="line">    moreInfo:&quot;错误详情&quot;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>其中’data’中返回的才是我们真正需要的内容，而‘errorCode’不为200，则是后台出错，具体错误信息放在‘moreInfo’中。<br>而如果直接使用Retrofit+RxJava。如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">/** </span><br><span class="line"> * 登录 </span><br><span class="line"> */  </span><br><span class="line">@POST  </span><br><span class="line">@FormUrlEncoded  </span><br><span class="line">Observable&lt;UserVO&gt; login(@Url String url , @FieldMap Map&lt;String,Object&gt;param);</span><br></pre></td></tr></table></figure>
<p>如果直接使用该接口，那么需要后台直接返回‘UserVO’的json数据。<br>但是依照前面所说，后台所有的返回数据都是依照</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;  </span><br><span class="line">    data:返回的数据,  </span><br><span class="line">    errorCode:200,  </span><br><span class="line">    moreInfo:&quot;错误详情&quot;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这种格式的数据返回。所以请求这个接口后，其实真正返回的数据应该是如下这样：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;  </span><br><span class="line">    data:&#123;UserVO对象&#125;,  </span><br><span class="line">    errorCode:200,  </span><br><span class="line">    moreInfo:&quot;错误详情&quot;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如上只是一个例子而已，其实所有接口，都是依照这种格式回传，所以在Retrofit+RxJava框架对返回的数据</p>
<p>进行处理之前，需要自己提前处理一下，先判断’errorCode’是否为200,如果为200就是正常请求数据返回，然后</p>
<p>获取到data的数据返回给Retrofit+RxJava框架进行处理。如果不为200，则为错误，根据错误的类型进行相应的处理。</p>
<p>如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">/** </span><br><span class="line">    * 统一处理原始数据 </span><br><span class="line">    * </span><br><span class="line">    * @param originalResponse </span><br><span class="line">    */  </span><br><span class="line">   private static Response dealResponseData(Response originalResponse) &#123;  </span><br><span class="line">       String jsonString = null;  </span><br><span class="line">       try &#123;  </span><br><span class="line">           BufferedSource bufferedSource = originalResponse.body().source();  </span><br><span class="line">           jsonString = bufferedSource.readString(Charset.forName(&quot;utf-8&quot;));  </span><br><span class="line">       &#125; catch (Exception e) &#123;  </span><br><span class="line">           e.printStackTrace();  </span><br><span class="line">       &#125;  </span><br><span class="line">       if (!jsonString.trim().startsWith(&quot;&#123;&quot;) &amp;&amp; !jsonString.trim().startsWith(&quot;[&quot;)) &#123;  </span><br><span class="line">           return onSuccess(originalResponse, jsonString);  </span><br><span class="line">       &#125;  </span><br><span class="line">       ResponseMessageBean msgBean = ResponseMessageBean.analyseReponse(jsonString);  </span><br><span class="line">       if (msgBean == null) return onSuccess(originalResponse, msgBean.data.toString());  </span><br><span class="line">       if (msgBean != null &amp;&amp; (msgBean.errorCode == 200)) &#123;  </span><br><span class="line">           showError = true;  </span><br><span class="line">           if (msgBean.data != null) &#123;  </span><br><span class="line">               return onSuccess(originalResponse, msgBean.data.toString());  </span><br><span class="line">           &#125; else &#123;  </span><br><span class="line">               return originalResponse.newBuilder().body(null).build();  </span><br><span class="line">           &#125;  </span><br><span class="line">       &#125; else &#123;  </span><br><span class="line">           onFailed(msgBean);  </span><br><span class="line">           throw new RuntimeException(msgBean.moreInfo.toString());  </span><br><span class="line">       &#125;  </span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
<p>请求之后返回一个Response对象，预先处理完成之后返回另一新的Response对象，这样就可以实现刚才的目的了。<br>ResponseMessageBean其实就是最外面的对象。<br>onSuccess方法中，其实主要对处理后的数据重新组装成一个新的Response对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">private static Response onSuccess(Response originalResponse, String content) &#123;  </span><br><span class="line">        return originalResponse.newBuilder().  </span><br><span class="line">                body(ResponseBody.create(null, content)).  </span><br><span class="line">                build();  </span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>方法虽然简单，但是这里要注意一点，不能新建一个新的Response返回，因为你Response里面其实是有多数据的，你就使用原来的Response，<br>然后把body里面的内容替换下就好了。<br>其实这里还有一个onFailed方法，主要是后台请求报错了，没有返回200，就根据你自己后台定义的值来判断具体错误，然后具体处理，这里<br>我就不再具体描述了。</p>
<p>前面描述的是data返回值是一个对象，其实是一个数组也是一样的，只要你在泛型里面写的是List那么就会返回一个List对象，如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">@POST  </span><br><span class="line">   @FormUrlEncoded  </span><br><span class="line">   Observable&lt;List&lt;UserVO&gt;&gt; userList(@Url String url , @FieldMap Map&lt;String,Object&gt;param);</span><br></pre></td></tr></table></figure>
<p>这样处理的数据其实是这种格式的</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;  </span><br><span class="line">    data:[&#123;&#125;,&#123;&#125;],  </span><br><span class="line">    errorCode:200,  </span><br><span class="line">    moreInfo:&quot;错误详情&quot;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>对了，我这里一直没有讲为什么Retrofit+RxJava会对返回的对象进行自动转换，因为我前面已经放了几篇文章，希望大家能先阅读了</p>
<p>一些基础的知识后，再来看这篇文章的具体封装，可能对你的帮助会更大一点。</p>
<p>Retrofit在初始化：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Retrofit retrofit = new Retrofit.Builder().baseUrl(UrlConstant.BASEURL).  </span><br><span class="line">               addConverterFactory(GsonConverterFactory.create()).  </span><br><span class="line">               addCallAdapterFactory(RxJavaCallAdapterFactory.create()).  </span><br><span class="line">               client(mOkHttpClient).  </span><br><span class="line">               build();</span><br></pre></td></tr></table></figure>
<p>addConverterFactory其实是为了对返回内容的提供一个转换器。<br>这里官方实现了很多种转换器，如下</p>
<p>Gson: com.squareup.retrofit:converter-gson<br>Jackson: com.squareup.retrofit:converter-jackson<br>Moshi: com.squareup.retrofit:converter-moshi<br>Protobuf: com.squareup.retrofit:converter-protobuf<br>Wire: com.squareup.retrofit:converter-wire<br>Simple XML: com.squareup.retrofit:converter-simplexml<br>一共有这么几种，大家可以根据自己的返回格式和喜好，选择对应的转换器，我这里选择了Gson转换器。记得选择转换器，要引入对应的依赖，这里我就不再过多赘述了。</p>
<p>我这里为什么要讲这个转换器呢？因为在项目的的过程中，我发现了有这样的一个需求，就是返回值中的data不是对象，也不是数组，<br>如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;  </span><br><span class="line">    data:&quot;你好&quot;,  </span><br><span class="line">    errorCode:200,  </span><br><span class="line">    moreInfo:&quot;错误详情&quot;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>或者是其他‘boolean’，‘int’等基础类型。就会出错。所以我这里重新对gson转换器做了封装，如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">public class TWGsonResponseBodyConverter&lt;T&gt; implements Converter&lt;ResponseBody, T&gt; &#123;  </span><br><span class="line">  </span><br><span class="line">    private final Gson gson;  </span><br><span class="line">    private final TypeAdapter&lt;T&gt; adapter;  </span><br><span class="line">    private final TypeToken&lt;?&gt; typeToken;  </span><br><span class="line">  </span><br><span class="line">    TWGsonResponseBodyConverter(Gson gson, TypeAdapter&lt;T&gt; adapter, TypeToken&lt;?&gt; typeToken) &#123;  </span><br><span class="line">        this.gson = gson;  </span><br><span class="line">        this.adapter = adapter;  </span><br><span class="line">        this.typeToken = typeToken;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    @Override  </span><br><span class="line">    public T convert(ResponseBody value) throws IOException &#123;  </span><br><span class="line">        Object obj = checkBasicType(value);  </span><br><span class="line">        if (obj != null) return (T) obj;  </span><br><span class="line">        JsonReader jsonReader = gson.newJsonReader(value.charStream());  </span><br><span class="line">        try &#123;  </span><br><span class="line">            return adapter.read(jsonReader);  </span><br><span class="line">        &#125; finally &#123;  </span><br><span class="line">            value.close();  </span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 如果是基本类型就转化后，返回 </span><br><span class="line">     */  </span><br><span class="line">    private Object checkBasicType(ResponseBody value) throws IOException &#123;  </span><br><span class="line">        String typeName = typeToken.getRawType().getSimpleName();  </span><br><span class="line">        if (&quot;String&quot;.equals(typeName)) &#123;  </span><br><span class="line">            return value.string();  </span><br><span class="line">        &#125; else if (&quot;Boolean&quot;.equals(typeName)) &#123;  </span><br><span class="line">            return Boolean.parseBoolean(value.string());  </span><br><span class="line">        &#125; else if (&quot;Integer&quot;.equals(typeName)) &#123;  </span><br><span class="line">            return Integer.parseInt(value.string());  </span><br><span class="line">        &#125;  </span><br><span class="line">        return null;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在方法中判断是否为基础类型，如果为基础类型，或者String 就通过处理后，直接返回，如果不是，则还是通过原来的转换器转换。<br>这样子就可以适用所有情况了。<br>在我的项目中，有一个场景，就是需要在请求时，自定义请求头，虽然Retrofit有@Head，但是由于每次请求都需要设置，还是直接封装<br>在里面比较好，代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">private static Request.Builder createRequestHeader(Request.Builder builder) &#123;  </span><br><span class="line">        builder.header(&quot;Content-Type&quot;,  </span><br><span class="line">                &quot;application/x-www-form-urlencoded&quot;);  </span><br><span class="line">        builder.header(&quot;User-Agent&quot;, getUserAgent());  </span><br><span class="line">        return builder;  </span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>其实就是创建一个新的Request返回而已。<br>然后项目中又说要使用https来访问，所以我又加了下面的代码来支持：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">if (mOkHttpClient == null) &#123;  </span><br><span class="line">                    try &#123;  </span><br><span class="line">                        X509TrustManager xtm = new X509TrustManager() &#123;  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public void checkClientTrusted(X509Certificate[] chain, String authType) &#123;  </span><br><span class="line">                            &#125;  </span><br><span class="line">  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public void checkServerTrusted(X509Certificate[] chain, String authType) &#123;  </span><br><span class="line">                            &#125;  </span><br><span class="line">  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public X509Certificate[] getAcceptedIssuers() &#123;  </span><br><span class="line">                                X509Certificate[] x509Certificates = new X509Certificate[0];  </span><br><span class="line">                                return x509Certificates;  </span><br><span class="line">                            &#125;  </span><br><span class="line">                        &#125;;  </span><br><span class="line">  </span><br><span class="line">                        SSLContext sslContext = null;  </span><br><span class="line">                        try &#123;  </span><br><span class="line">                            sslContext = SSLContext.getInstance(&quot;SSL&quot;);  </span><br><span class="line">  </span><br><span class="line">                            sslContext.init(null, new TrustManager[]&#123;xtm&#125;, new SecureRandom());  </span><br><span class="line">  </span><br><span class="line">                        &#125; catch (NoSuchAlgorithmException e) &#123;  </span><br><span class="line">                            e.printStackTrace();  </span><br><span class="line">                        &#125; catch (KeyManagementException e) &#123;  </span><br><span class="line">                            e.printStackTrace();  </span><br><span class="line">                        &#125;  </span><br><span class="line">                        HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() &#123;  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public boolean verify(String hostname, SSLSession session) &#123;  </span><br><span class="line">                                return true;  </span><br><span class="line">                            &#125;  </span><br><span class="line">                        &#125;;  </span><br><span class="line">  </span><br><span class="line">                        // 指定缓存路径,缓存大小100Mb  </span><br><span class="line">                        Cache cache = new Cache(new File(mContext.getCacheDir(), &quot;HttpCache&quot;), 1024 * 1024 * 100);  </span><br><span class="line">                        mOkHttpClient = new OkHttpClient.Builder().  </span><br><span class="line">                                addInterceptor(mRewriteCacheControlInterceptor).  </span><br><span class="line">                                retryOnConnectionFailure(false).  </span><br><span class="line">                                connectTimeout(30, TimeUnit.SECONDS).  </span><br><span class="line">                                sslSocketFactory(sslContext.getSocketFactory()).  </span><br><span class="line">                                hostnameVerifier(DO_NOT_VERIFY).  </span><br><span class="line">                                cache(cache).  </span><br><span class="line">                                build();  </span><br><span class="line">                    &#125; catch (Exception e) &#123;  </span><br><span class="line">                        e.printStackTrace();  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">            &#125;</span><br></pre></td></tr></table></figure>
<p>并且还指定了缓存还有超时时间，重试次数，等等。</p>
<p>以上情况其实已经适用我当前项目的所以场景了。</p>
<p>下面是附上所有代码：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br></pre></td><td class="code"><pre><span class="line">public class RetrofitHelper &#123;  </span><br><span class="line">    private static ServerApi api;  </span><br><span class="line">    private static OkHttpClient mOkHttpClient;  </span><br><span class="line">    private static Context mContext;  </span><br><span class="line">    private static boolean showError = true;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 启动后初始化 </span><br><span class="line">     */  </span><br><span class="line">    public static void init(Context context) &#123;  </span><br><span class="line">        mContext = context;  </span><br><span class="line">        initOkHttpClient();  </span><br><span class="line">        Retrofit retrofit = new Retrofit.Builder().baseUrl(UrlConstant.BASEURL).  </span><br><span class="line">                addConverterFactory(GsonConverterFactory.create()).  </span><br><span class="line">                addCallAdapterFactory(RxJavaCallAdapterFactory.create()).  </span><br><span class="line">                client(mOkHttpClient).  </span><br><span class="line">                build();  </span><br><span class="line">        api = retrofit.create(ServerApi.class);  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 重置baseUrl </span><br><span class="line">     */  </span><br><span class="line">    public static void resetBaseUrl() &#123;  </span><br><span class="line">        Retrofit retrofit = new Retrofit.Builder().baseUrl(UrlConstant.BASEURL).  </span><br><span class="line">                addConverterFactory(TWGsonConverterFactory.create()).  </span><br><span class="line">                addCallAdapterFactory(RxJavaCallAdapterFactory.create()).  </span><br><span class="line">                client(mOkHttpClient).  </span><br><span class="line">                build();  </span><br><span class="line">        api = retrofit.create(ServerApi.class);  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">    public static ServerApi getApi() &#123;  </span><br><span class="line">        return api;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 统一处理原始数据 </span><br><span class="line">     * </span><br><span class="line">     * @param originalResponse </span><br><span class="line">     */  </span><br><span class="line">    private static Response dealResponseData(Response originalResponse) &#123;  </span><br><span class="line">        String jsonString = null;  </span><br><span class="line">        try &#123;  </span><br><span class="line">            BufferedSource bufferedSource = originalResponse.body().source();  </span><br><span class="line">            jsonString = bufferedSource.readString(Charset.forName(&quot;utf-8&quot;));  </span><br><span class="line">        &#125; catch (Exception e) &#123;  </span><br><span class="line">            e.printStackTrace();  </span><br><span class="line">        &#125;  </span><br><span class="line">        if (!jsonString.trim().startsWith(&quot;&#123;&quot;) &amp;&amp; !jsonString.trim().startsWith(&quot;[&quot;)) &#123;  </span><br><span class="line">            return onSuccess(originalResponse, jsonString);  </span><br><span class="line">        &#125;  </span><br><span class="line">        ResponseMessageBean msgBean = ResponseMessageBean.analyseReponse(jsonString);  </span><br><span class="line">        if (msgBean == null) return onSuccess(originalResponse, msgBean.data.toString());  </span><br><span class="line">        if (msgBean != null &amp;&amp; (msgBean.errorCode == 200)) &#123;  </span><br><span class="line">            showError = true;  </span><br><span class="line">            if (msgBean.data != null) &#123;  </span><br><span class="line">                return onSuccess(originalResponse, msgBean.data.toString());  </span><br><span class="line">            &#125; else &#123;  </span><br><span class="line">                return originalResponse.newBuilder().body(null).build();  </span><br><span class="line">            &#125;  </span><br><span class="line">        &#125; else &#123;  </span><br><span class="line">            onFailed(msgBean);  </span><br><span class="line">            throw new RuntimeException(msgBean.moreInfo.toString());  </span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 初始化okHttp </span><br><span class="line">     */  </span><br><span class="line">    private static void initOkHttpClient() &#123;  </span><br><span class="line">        if (mOkHttpClient == null) &#123;  </span><br><span class="line">            synchronized (RetrofitHelper.class) &#123;  </span><br><span class="line">                Interceptor mRewriteCacheControlInterceptor = new Interceptor() &#123;  </span><br><span class="line">                    @Override  </span><br><span class="line">                    public Response intercept(Chain chain) throws IOException &#123;  </span><br><span class="line">                        Request request = chain.request();  </span><br><span class="line">                        if (!NetworkUtils.isNetworkConnected(mContext)) &#123;  </span><br><span class="line">                            request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();  </span><br><span class="line">                        &#125;  </span><br><span class="line">                        /** </span><br><span class="line">                         * 统一设置请求头 </span><br><span class="line">                         */  </span><br><span class="line">                        Request newRequest = createRequestHeader(request.newBuilder()).build();  </span><br><span class="line">                        Response originalResponse = chain.proceed(newRequest);  </span><br><span class="line">                        //如果是重定向，那么就执行重定向后返回数据。  </span><br><span class="line">                        if (originalResponse.isRedirect()) &#123;  </span><br><span class="line">                            Request redirectRequest = request.newBuilder().url(originalResponse.header(&quot;location&quot;)).build();  </span><br><span class="line">                            originalResponse = chain.proceed(redirectRequest);  </span><br><span class="line">                        &#125;  </span><br><span class="line">                        originalResponse = dealResponseData(originalResponse);  </span><br><span class="line">                        return originalResponse;  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;;  </span><br><span class="line">  </span><br><span class="line">                if (mOkHttpClient == null) &#123;  </span><br><span class="line">                    try &#123;  </span><br><span class="line">                        X509TrustManager xtm = new X509TrustManager() &#123;  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public void checkClientTrusted(X509Certificate[] chain, String authType) &#123;  </span><br><span class="line">                            &#125;  </span><br><span class="line">  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public void checkServerTrusted(X509Certificate[] chain, String authType) &#123;  </span><br><span class="line">                            &#125;  </span><br><span class="line">  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public X509Certificate[] getAcceptedIssuers() &#123;  </span><br><span class="line">                                X509Certificate[] x509Certificates = new X509Certificate[0];  </span><br><span class="line">                                return x509Certificates;  </span><br><span class="line">                            &#125;  </span><br><span class="line">                        &#125;;  </span><br><span class="line">  </span><br><span class="line">                        SSLContext sslContext = null;  </span><br><span class="line">                        try &#123;  </span><br><span class="line">                            sslContext = SSLContext.getInstance(&quot;SSL&quot;);  </span><br><span class="line">  </span><br><span class="line">                            sslContext.init(null, new TrustManager[]&#123;xtm&#125;, new SecureRandom());  </span><br><span class="line">  </span><br><span class="line">                        &#125; catch (NoSuchAlgorithmException e) &#123;  </span><br><span class="line">                            e.printStackTrace();  </span><br><span class="line">                        &#125; catch (KeyManagementException e) &#123;  </span><br><span class="line">                            e.printStackTrace();  </span><br><span class="line">                        &#125;  </span><br><span class="line">                        HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() &#123;  </span><br><span class="line">                            @Override  </span><br><span class="line">                            public boolean verify(String hostname, SSLSession session) &#123;  </span><br><span class="line">                                return true;  </span><br><span class="line">                            &#125;  </span><br><span class="line">                        &#125;;  </span><br><span class="line">  </span><br><span class="line">                        // 指定缓存路径,缓存大小100Mb  </span><br><span class="line">                        Cache cache = new Cache(new File(mContext.getCacheDir(), &quot;HttpCache&quot;), 1024 * 1024 * 100);  </span><br><span class="line">                        mOkHttpClient = new OkHttpClient.Builder().  </span><br><span class="line">                                addInterceptor(mRewriteCacheControlInterceptor).  </span><br><span class="line">                                retryOnConnectionFailure(false).  </span><br><span class="line">                                connectTimeout(30, TimeUnit.SECONDS).  </span><br><span class="line">                                sslSocketFactory(sslContext.getSocketFactory()).  </span><br><span class="line">                                hostnameVerifier(DO_NOT_VERIFY).  </span><br><span class="line">                                cache(cache).  </span><br><span class="line">                                build();  </span><br><span class="line">                    &#125; catch (Exception e) &#123;  </span><br><span class="line">                        e.printStackTrace();  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">            &#125;  </span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">    private static Response onSuccess(Response originalResponse, String content) &#123;  </span><br><span class="line">        return originalResponse.newBuilder().  </span><br><span class="line">                body(ResponseBody.create(null, content)).  </span><br><span class="line">                build();  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * errorCode 不为200 </span><br><span class="line">     * </span><br><span class="line">     * @param msgBean </span><br><span class="line">     */  </span><br><span class="line">    private static void onFailed(ResponseMessageBean msgBean) &#123;  </span><br><span class="line">        String alert = &quot;&quot;;  </span><br><span class="line">        if (msgBean == null) &#123;  </span><br><span class="line">            return;  </span><br><span class="line">        &#125;  </span><br><span class="line">        if (msgBean.errorCode != 200) &#123;  </span><br><span class="line">            if (msgBean.errorCode == 401) &#123;  </span><br><span class="line">                Observable.create(new Observable.OnSubscribe&lt;Object&gt;() &#123;  </span><br><span class="line">                    @Override  </span><br><span class="line">                    public void call(Subscriber&lt;? super Object&gt; subscriber) &#123;  </span><br><span class="line">                        DialogUtils.alertUserUnauthorized(mContext);  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;).subscribeOn(AndroidSchedulers.mainThread()).subscribe(new Observer&lt;Object&gt;() &#123;  </span><br><span class="line">                    @Override  </span><br><span class="line">                    public void onCompleted() &#123;  </span><br><span class="line">                    &#125;  </span><br><span class="line">  </span><br><span class="line">                    @Override  </span><br><span class="line">                    public void onError(Throwable e) &#123;  </span><br><span class="line">                    &#125;  </span><br><span class="line">  </span><br><span class="line">                    @Override  </span><br><span class="line">                    public void onNext(Object o) &#123;  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;);  </span><br><span class="line">  </span><br><span class="line">                return;  </span><br><span class="line">            &#125; else if (msgBean.errorCode == 301) &#123;  </span><br><span class="line">                alert = &quot;服务器繁忙，请稍后再试&quot;;  </span><br><span class="line">            &#125; else if (msgBean.errorCode == 302) &#123;  </span><br><span class="line">                alert = &quot;此次访问已失效哦&quot;;  </span><br><span class="line">            &#125; else if (msgBean.errorCode == 403) &#123;  </span><br><span class="line">                alert = &quot;接口临时关闭，请稍后再试&quot;;  </span><br><span class="line">            &#125; else if (msgBean.errorCode == 500) &#123;  </span><br><span class="line">                alert = &quot;服务器繁忙，请稍后再试&quot;;  </span><br><span class="line">            &#125; else if (msgBean.errorCode == -1) &#123;  </span><br><span class="line">                showError = true;  </span><br><span class="line">                if (msgBean.moreInfo != null) &#123;  </span><br><span class="line">                    alert = msgBean.moreInfo.toString();  </span><br><span class="line">                &#125;  </span><br><span class="line">            &#125; else &#123;  </span><br><span class="line">                return;  </span><br><span class="line">            &#125;  </span><br><span class="line">            final String alertStr = alert;  </span><br><span class="line">  </span><br><span class="line">            Observable.create(new Observable.OnSubscribe&lt;Object&gt;() &#123;  </span><br><span class="line">                @Override  </span><br><span class="line">                public void call(Subscriber&lt;? super Object&gt; subscriber) &#123;  </span><br><span class="line">                    //这里有 window bad token 错误  </span><br><span class="line">                    try &#123;  </span><br><span class="line">                        if (showError &amp;&amp; !TextUtils.isEmpty(alertStr)) &#123;  </span><br><span class="line">                            ToastUtils.showToast(mContext, alertStr);  </span><br><span class="line">                            showError = false;  </span><br><span class="line">                        &#125;  </span><br><span class="line">                    &#125; catch (Exception e) &#123;  </span><br><span class="line">                        e.printStackTrace();  </span><br><span class="line">                    &#125;  </span><br><span class="line">                &#125;  </span><br><span class="line">            &#125;).subscribeOn(AndroidSchedulers.mainThread()).subscribe();  </span><br><span class="line">        &#125;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">    /** </span><br><span class="line">     * 统一处理请求头部数据 </span><br><span class="line">     * </span><br><span class="line">     * @return </span><br><span class="line">     */  </span><br><span class="line">  </span><br><span class="line">    private static Request.Builder createRequestHeader(Request.Builder builder) &#123;  </span><br><span class="line">        builder.header(&quot;Content-Type&quot;,  </span><br><span class="line">                &quot;application/x-www-form-urlencoded&quot;);  </span><br><span class="line">        builder.header(&quot;User-Agent&quot;, getUserAgent());  </span><br><span class="line">        return builder;  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line">    public static String getUserAgent() &#123;  </span><br><span class="line">        UserAgentBean userAgent = new UserAgentBean();  </span><br><span class="line">        userAgent.setDeviceToken(AppUtils.getDeviceId(mContext));  </span><br><span class="line">        userAgent.setClient(&quot;Android&quot;);  </span><br><span class="line">        userAgent.setChannel(&quot;xunbao&quot;);  </span><br><span class="line">        if (User.getCurrent() != null) &#123;  </span><br><span class="line">            userAgent.setUserId(User.getCurrent().getId());  </span><br><span class="line">        &#125;  </span><br><span class="line">        PackageInfo info = AppUtils.getPackageInfo(mContext);  </span><br><span class="line">        if (info != null) &#123;  </span><br><span class="line">            userAgent.setBuild(info.versionCode + &quot;&quot;);  </span><br><span class="line">            userAgent.setVersion(info.versionName);  </span><br><span class="line">        &#125;  </span><br><span class="line">        userAgent.setScreenSize(  </span><br><span class="line">                DisplayUtils.getScreenSize(mContext));  </span><br><span class="line">        userAgent.setSafeToken(SharePerferenceUtils.getString(mContext,PreferenceConstant.SAFE_TOKEN));  </span><br><span class="line">        return userAgent.toString();  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>Donate comment here</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/jexo/images/wechatpay.png" alt="Ling Hu 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/jexo/images/alipay.png" alt="Ling Hu 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/jexo/tags/Android/" rel="tag"># Android</a>
          
            <a href="/jexo/tags/封装/" rel="tag"># 封装</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/jexo/2018/04/18/Retrofit2-RxJava-Dagger2-MVP完美封装/" rel="next" title="Retrofit2-RxJava-Dagger2-MVP完美封装">
                <i class="fa fa-chevron-left"></i> Retrofit2-RxJava-Dagger2-MVP完美封装
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/jexo/2018/04/18/Android HAL层开发/" rel="prev" title="Android HAL层开发">
                Android HAL层开发 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      
        <div id="gitment-container"></div>
      
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      

      <section class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/jexo/images/avatar.jpg"
                alt="Ling Hu" />
            
              <p class="site-author-name" itemprop="name">Ling Hu</p>
              <p class="site-description motion-element" itemprop="description">Android,源码解析,每天进步一点点</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/jexo/archives/">
              
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/jexo/categories/index.html">
                  <span class="site-state-item-count">9</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/jexo/tags/index.html">
                  <span class="site-state-item-count">14</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/javalong" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Ling Hu</span>

  
</div>









        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/jexo/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/jexo/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/jexo/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/jexo/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/jexo/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/jexo/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/jexo/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  







<!-- LOCAL: You can save these files to your site and update links -->
    
        
        <link rel="stylesheet" href="https://aimingoo.github.io/gitmint/style/default.css">
        <script src="https://aimingoo.github.io/gitmint/dist/gitmint.browser.js"></script>
    
<!-- END LOCAL -->

    
      <style>
        a.gitment-editor-footer-tip { display: none; }
        .gitment-container.gitment-footer-container { display: none; }
      </style>
    

    
      <script type="text/javascript">
      function renderGitment(){
        var gitment = new Gitmint({
            id: getId(),
            owner: 'javalong',
            repo: 'RxJava-Operator',
            
            lang: "zh-Hans" || navigator.language || navigator.systemLanguage || navigator.userLanguage,
            
            oauth: {
            
            
                client_secret: '06b042e57b8420f5002a6407348dde078bcde761',
            
                client_id: '1b5481d6512b2f28d7a2'
            }});
        gitment.render('gitment-container');
      }

      function getId(){
            if( window.location.pathname.length>=50){
                return window.location.pathname.substr(0,50)
            }else{
                return window.location.pathname
            }
      }

      
      renderGitment();
      
      </script>
    







  





  

  

  

  
  

  

  

  

</body>
</html>
